#include <dos.h>
#include <stdio.h>
#include "ae.h"
#include <stddef.h>

/********* swap buff ***********/

#define MAXBUF 16384
#define CHECKMAX MAXBUF/2
#define MAXCLUSTER 61700

unsigned int wbuf0[CHECKMAX];
unsigned int wbuf1[CHECKMAX];

unsigned char wbuf0_full, wbuf1_full;
unsigned long wbuf_count;
unsigned char wmode;
int wcount = 0;
// Control bytes for single ended, internal clock mode of ADS8344
unsigned char c_byte[] = { 0x86, 0xc6, 0x96, 0xd6, 0xa6, 0xe6, 0xb6, 0xf6 };

/******** interrupt *********/
void interrupt far t2_isr (void);
void interrupt far t1_isr (void);

/************* for File write *************/
#include "mm8.h"
#include "fileio.h"
#include "filegeo.h"

#define FS_NO_DMA
char fstatus;

void PAUSE (void);
unsigned char k;
unsigned int fb_ad16 (unsigned char k);
int i, ledd = 0, ledd2 = 0;

/*********** LED **********/
const int LED_YELLOW = 17;
const int LED_GREEN = 25;
const int LED_ORANGE = 24;
const int LED_RED = 3;

/*********** LED **********/
const int Button = 21;

/*********** on/off **********/
const int on = 1;
const int off = 0;

/*********** AD Convector **********/

#define ADB 0x120
#define ADA 0x124
#define CV 0x140

/********** File size parameter ********/
int cluster_count = 5;

/********** frequency control ********/
unsigned int period = 30;

/****Program start address: 0x60000 *******/

struct fs_descrip *
filesys_init (void)
{
  struct fs_descrip *l_retval = NULL;
  char filename[FNLEN + 2];
  int l_index = 0;

//   fs_setFlags(FS_NO_DMA0);
  if (fs_initPCFlash () != 0)
    return NULL;

  while (l_index < 100)
    {
      sprintf (filename, "data%d.bin", l_index++);

      if ((l_retval = fs_fopen (filename, O_WRONLY)) != NULL)
	{
	  if (l_retval->ff_status == fOK)
	    return l_retval;

	  /* This file doesn't work for one reason or another.. */
	  fs_fclose (l_retval);
	}
      else
	/* Only reason l_retval would be NULL is if you are completely
	   out of memory... */
	return NULL;
    }
  return l_retval;
}

void
main (void)
{
  char current_key;
  int tm, ta, tb;
  //unsigned long cluster_count;
  char quit;
  struct fs_descrip *file;
  struct ff_geo *l_geo;
  //char out[10];

  wbuf0_full = 0;
  wbuf1_full = 0;
  wmode = 0;

  ae_init ();			// AE86 initialization
  pio_init (18, 0);
  //outport (0xfff2, 0);

  pio_init (9, 1);		// A19=P9 as input for ADC data output DOUT
  pio_init (2, 0);		// P2 as PCS6

  pio_init (12, 2);
  pio_wr (12, 0);

  pio_init (Button, 1);		// press key p21

  pio_init (LED_YELLOW, 2);	// led 1         red
  pio_init (LED_GREEN, 2);	// led 2        yellow
  pio_init (LED_ORANGE, 2);	// led 3        green
  pio_init (LED_RED, 2);	// led 4        blue
  pio_wr (LED_YELLOW, on);
  pio_wr (LED_GREEN, on);
  pio_wr (LED_ORANGE, on);
  pio_wr (LED_RED, on);

  // open a new file
  quit = 0;

  led (off);
  file = filesys_init ();
  l_geo = fs_GetGeometry ();
  fs_callocate (file, cluster_count);
  if (!file)
    {
      pio_wr (LED_RED, on);
      quit = 1;
    }
  else
    {
      pio_wr (LED_RED, off);
      quit = 0;
    }
  pio_wr (LED_YELLOW, off);
  pio_wr (LED_GREEN, off);
  pio_wr (LED_ORANGE, off);

//Attempt init filesystem.
  while (quit)
    {
      file = filesys_init ();
      l_geo = fs_GetGeometry ();
      fs_callocate (file, cluster_count);
      if (!file)
	{
	  pio_wr (LED_RED, on);
	  quit = 1;
	}
      else
	{
	  pio_wr (LED_RED, off);
	  quit = 0;
	}
      //delay_ms(500);
    }

  outport (0xffa2, 0x7fbc);
  outport (0xffa4, 0x0075);
  //Turn on green light when filesystem is ready
  pio_wr (LED_GREEN, on);

  //Wait until user start recording ECG
  PAUSE ();
  led (on);
  pio_wr (LED_GREEN, off);
  pio_wr (LED_ORANGE, on);
  pio_wr (LED_RED, on);
  ta = (unsigned int) 301;	//
  tm = 0xc001;			//      start 1/4 clk countdown, int. dis-enabled
  t2_init (tm, ta, t2_isr);
  pio_init (1, 0);
  ta = (unsigned int) period;	//
  tb = (unsigned int) period;	//
  tm = 0xe00b;			//      start timer1 prescale countdown, int. enabled
  t1_init (tm, ta, tb, t1_isr);

  i = 0;
  // All control pins high; Start AD conversion
  for (i = 0; i < 8; i++)
    {
      outportb (0x600 + i, 0xff);
    }
  while (quit == 0)
    {
      switch (wmode)
	{
	case 0:
	  if (wbuf1_full == 1)
	    {			//save buff1 to file
	      fstatus = fs_fputcluster ((unsigned char *) (&wbuf1), file);
	      wcount++;
	      pio_wr (LED_YELLOW, off);
	      pio_wr (LED_ORANGE, on);
	      wbuf1_full = 0;

	      cluster_count--;
	    }
	  break;
	case 1:
	  if (wbuf0_full == 1)
	    {			//save buff0 to file
	      fstatus = fs_fputcluster ((unsigned char *) (&wbuf0), file);
	      wcount++;
	      pio_wr (LED_YELLOW, on);
	      pio_wr (LED_ORANGE, off);
	      wbuf0_full = 0;

	      cluster_count--;
	    }
	}
      if (cluster_count == 0)
	{
	  pio_wr (LED_YELLOW, off);
	  pio_wr (LED_GREEN, on);
	  pio_wr (LED_ORANGE, off);
	  pio_wr (LED_RED, off);
	  quit = 1;
	}
    }

  t1_init (0x0000, 0, 0, t1_isr);	// turn off timer
  fs_fclose (file);
}

void interrupt far
t1_isr (void)
{
  //inport(CV); // start conversion for AA1 and AB1
  switch (wmode)
    {
    case 0:
      if (wbuf0_full == 0)
	{
	  wbuf0[wbuf_count] = fb_ad16 (c_byte[0]);
	  if (wbuf_count < CHECKMAX - 1)
	    {
	      wbuf_count++;
	    }
	  else
	    {
	      wbuf_count = 0;
	      wmode = 1;
	      wbuf0_full = 1;
	    }
	  break;
	}
      else
	{
	  t1_init (0x0000, 0, 0, t1_isr);	//turn off timer
	  pio_wr (3, 1);
	  pio_wr (17, 1);
	  pio_wr (24, 0);
	  pio_wr (25, 0);
	}
      break;

    case 1:
      if (wbuf1_full == 0)
	{
	  wbuf1[wbuf_count] = fb_ad16 (c_byte[0]);
	  if (wbuf_count < CHECKMAX - 1)
	    {
	      wbuf_count++;
	    }
	  else
	    {
	      wbuf_count = 0;
	      wmode = 0;
	      wbuf1_full = 1;
	    }
	  break;
	}
      else
	{
	  t1_init (0x0000, 0, 0, t1_isr);
	  pio_wr (3, 1);
	  pio_wr (17, 0);
	  pio_wr (24, 0);
	  pio_wr (25, 1);
	}
      break;
    }
  outport (0xff22, 0x0008);	// issue EOI for the interrupt.
}

void
PAUSE (void)
{
  while ((pio_rd (1) & 0x0020) == 0x0020)
    {
    }				// loop until p24 key is pressed.
  while ((pio_rd (1) & 0x0020) == 0x0000)
    {
    }				// debounce. loop until p24 is released.
}

unsigned int
fb_ad16 (unsigned char k)
{
  unsigned int dat16;
  asm
  {
//      CK=0x603, /CS=0x606, DI=0x604, BSY=???, DOUT=A19=P9 read
    mov ax, 0603 h		// CK
      mov dx, ax;
    mov al, 0 h			// low
      out dx, al mov ax, 0604 h	// DI
      mov dx, ax;
    mov al, 0 h			// low
      out dx, al mov ax, 0606 h	// CS
      mov dx, ax;
    mov al, 0 h			// CS low
      out dx, al mov bh, k mov cx, 08 h	// 8-bit        control byte
  }
  ad1:asm
  {
    rcl bh, 1 jc vhigh mov ax, 0604 h	// DI
      mov dx, ax;
    mov al, 0 h			// low
    out dx, al jmp c_out}
  vhigh:asm
  {
    mov ax, 0604 h		// DI
      mov dx, ax;
    mov al, 01 h		// high
    out dx, al}
  c_out:asm
  {
    mov ax, 0603 h		// CK
      mov dx, ax;
    mov al, 01 h		// CK high, low to high latches control bit into ADC
      out dx, al mov al, 0 h	// CK low
    out dx, al loop ad1}
//      internal clock mode, 10 micro seconds wait for busy low
  delay_ms (1);
  asm
  {
    xor bx, bx			// clear bx ready for 16-bit data
      mov cx, 10 h		// 16-bit ADC bytes shift out on falling edge of CK
      mov ax, 0603 h		// CK
      mov dx, ax;
    mov al, 01 h		// CK high
      out dx, al mov al, 0 h	// CK low
    out dx, al}
  dati:asm
  {
// 0x0200&inport(0xff74);

    mov ax, 0f f74h		// DOUT read
      mov dx, ax;
    in ax, dx test ax, 0200 h	// test DOUT
      jz dout0 stc		// set carry
    jmp dout}
  dout0:asm
  {
    clc;			// clear carry
  }
  dout:asm
  {
    rcl bx, 1 mov ax, 0603 h	// CK
      mov dx, ax;
    mov al, 01 h		// CK high
      out dx, al mov al, 0 h	// CK low
      out dx, al loop dati mov ax, 0606 h	// CS
      mov dx, ax;
    mov al, 01 h		// CS high
    out dx, al mov ax, bx mov dat16, ax}
  return (dat16);
}

void interrupt far
t2_isr (void)
{
  /* Issue EOI for the interrupt */
  outport (0xff22, 0x0008);
}
